package cn.com.bsoft.webEx

import cn.com.bsoft.kotlinEx.StatusAndMessageError
import org.springframework.http.MediaType
import org.springframework.util.StreamUtils
import org.springframework.web.context.ContextLoader
import org.springframework.web.context.WebApplicationContext
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.*
import javax.servlet.ReadListener
import javax.servlet.ServletInputStream
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletRequestWrapper


fun httpServletRequest(): HttpServletRequest? {
    return try {
        val curRequest = (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes)
                .request
        curRequest
    }catch (e:Throwable){
        null
    }

}

val HttpServletRequest.webApplicationContext: WebApplicationContext
    get() {
        return ContextLoader.getCurrentWebApplicationContext()
                ?:cn.com.bsoft.webEx.webApplicationContext
                ?:throw StatusAndMessageError("没有找到WebApplicationContext")
    }

class BufferedServletInputStream(buffer: ByteArray) : ServletInputStream() {

    private val inputStream: ByteArrayInputStream = ByteArrayInputStream(buffer)

    private var _listener: ReadListener? = null

    @Throws(IOException::class)
    override fun available(): Int {
        return inputStream.available()
    }

    @Throws(IOException::class)
    override fun read(): Int {
        return inputStream.read()
    }

    @Throws(IOException::class)
    override fun read(b: ByteArray, off: Int, len: Int): Int {
        return inputStream.read(b, off, len)
    }

    override fun isReady(): Boolean {
        return true
    }

    override fun isFinished(): Boolean {
        return true
    }

    override fun setReadListener(listener: ReadListener?) {
        _listener = listener
    }
}


class MutableHttpServletRequest(request: HttpServletRequest) : HttpServletRequestWrapper(request) {

    val out: ByteArrayOutputStream = ByteArrayOutputStream()

    init {
        StreamUtils.copy(request.inputStream, out)
        out.flush()
    }

    override fun getContentType(): String {
        return super.getContentType() ?: MediaType.APPLICATION_JSON_VALUE
    }

    override fun getHeaders(name: String?): Enumeration<String> {
        var set = HashSet<String>()

        val e = super.getHeaders(name)
        while (e.hasMoreElements()) {
            val n = e.nextElement()
            set.add(n)
        }
        return Collections.enumeration(set)
    }

    override fun getHeader(name: String): String? {
        return (request as HttpServletRequest).getHeader(name)
    }

    // create a set of the custom header names
// now add the headers from the wrapped request object
// add the names of the request headers into the list
// create an enumeration from the set and return
    override fun getHeaderNames(): Enumeration<String> {
        val set = HashSet<String>()
        val e = (request as HttpServletRequest).headerNames
        while (e.hasMoreElements()) {
            val n = e.nextElement()
            set.add(n)
        }
        return Collections.enumeration(set)
    }

    override fun getInputStream(): ServletInputStream {
        val bytes = out.toByteArray()
        if (bytes.isNotEmpty()) {
            return BufferedServletInputStream(bytes)
        }
        return super.getInputStream()
    }

}